﻿// demon5-类和对象-2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
/*
如果类的成员函数中涉及多个对象，在这种情况下需要使用this指针。
this指针存放了对象的地址，它被作为隐藏参数传递给了成员函数，指向调用成员函数的对象（调用者对象）。
每个成员函数（包括构造函数和析构函数）都有一个this指针，可以用它访问调用者对象的成员。
（可以解决成员变量名与函数形参名相同的问题）
 this可以表示对象。
 如果在成员函数的括号后面使用const，那么将不能通过this指针修改成员变量。

 this指针的特性：
 1.在形参和实参的位置，不能显示写； 2.在函数内部可以使用
 
 this指针存在哪里？ 栈区,因为this指针是一个形参(有些编译比如vs可能会用寄存器存储）
*/

/*
#include <iostream>
using namespace std;
class DataTime
{
public:
    
    void  Init(int year=1,int month=1,int day=1)          //隐含的this指针
    {
        this->m_year = year;
        this->m_month = month;
        this->m_day = day;
        cout << "调用一次Init函数(),this指针的地址是："<<this <<endl;
    }
    //void Print(DataTime* const this) {}         // 在形参和实参的位置，不能显示写,这里会报错的
    void Print()
    {
        //this = nullptr;                         //this指针本身是const,不可修改的,强行修改则报错，但是this指向的内容可修改
        cout << m_year << "/" << m_month << "/" << m_day << endl;                   //这里输出的年月日信息并非下面的成员变量
        cout << this->m_year << "/" << this->m_month << "/" << this->m_day << endl; //this指针指向的内容是可以修改的
    }

private:
    int m_year;             //此处仅仅是声明，没有开空间，所以不会存在内存里面，定义跟着对象走的，就也是d1和d2
    int m_month;
    int m_day;
};


int main()                  //主函数
{
    DataTime d1;
    d1.Print();                        //打印的是随机的垃圾值  
    d1.Init(2024,9,11);                //
    d1.Print();

    DataTime d2; 
    cout << "\n调用对象d2" << endl;    //
    d2.Init(2024, 2, 11);              //
    d2.Print();
}
*/


/*
#include<iostream>
using namespace std;

class A
{
public:
    void Print() {
        cout << this << endl;                 //
        cout << "Print()" << endl;            //这里并没有解引用空指针
        //cout << m_a << endl;                //这里报错了，解引用空指针，即this->m_a,因为
    }
private:
    int m_a;
};

int main()
{
    A *a1=nullptr;
    a1->Print();                             //p->
    (*a1).Print();                           //正常运行
    return 0;
}
*/


/*
默认成员函数：构造函数、析构函数、拷贝构造、赋值重载、取地址重载

构造函数：在创建对象时，自动的进行初始化工作。
析构函数：在销毁对象前，自动的完成清理工作。
拷贝构造：使用同类对象初始化创建对象。
赋值重载：把一个对象赋值给另一个对象
取地址重载：普通对象和const修饰的对象取地址，这两个会很少实现

1）构造函数
语法：类名() { ...... }

   访问权限必须是public。
 函数名必须与类名相同。
   没有返回值，不写void。
 可以有参数，可以重载，可以有默认参数。
 创建对象时只会自动调用一次，不能手工调用。
   注：构造函数是默认成员函数，我们不写，编译器会默认生成一个，如果写了构造函数，编译器会使用我们自己写的，就不会默认自动生成
   在绝大多数场景下都需要我们自己手动编写构造函数。

2）析构函数
语法：~类名() { ...... }

   访问权限必须是public。
 函数名必须在类名前加~。
   没有返回值，也不写void。
 没有参数，不能重载。
 销毁对象前只会自动调用一次，但是可以手工调用。

*/


/*
#include<iostream>
using namespace std;

class A
{
public:
    A()
    {
        cout << "调用一次构造函数A()" << endl;
    }
    void Print(int year = 1, int month = 1,int day=1)
    {
        m_year = year;
        m_month = month;
        m_day = day;
        cout << m_year << "/" << m_month << "/" << m_day<<endl;
    }
    ~A()                                                        //析构函数是自动调用的
    {
        cout << "调用一次析构函数~A()" << endl;
    }
private:
    int m_year;
    int m_month;
    int m_day;
};

int main()
{
    A a1;
    a1.Print();                    // 调用默认缺省值  1/1/1
    a1.Print(2024,9,14);           // 调用传入的参数
    a1.~A();                       // 手动调用一次析构函数
}
*/



/*
#include<iostream>
using namespace std;

class Time
{
public:
    Time(int hour)                 //这里手动添加默认构造函数，编译器不会自动生成，则导致A也不会自动生成默认构造函数
    {
        cout << "调用一次Time的构造函数Time()->" << endl;
        m_hour = 0;
        m_minute = 0;
        m_second = 0;
    }
private:
    int m_hour;              //声明
    int m_minute;
    int m_second;
};

class A          //A没写构造函数，会默认自动生成，但是Time有自己的构造函数，编译器不会自动生成，则导致找不到A的默认构造函数的报错
{
private:
    //基本内置类型
    int m_year=1;         //声明缺省值,如果没写构造函数，默认初始值使用它
    int m_month=1;
    int m_day=1;
    //自定义类型
    Time _t;              //Time没有默认构造函数，会导致A也不能自动生成默认构造函数，报错
};

int main()
{
    A a1;
    return 0;
}
*/


/*
#include<iostream>
using namespace std;

class Time
{
       //编译器自动生成默认构造函数，但是对改变成员变量，所以 m_hour、m_minute、m_second都是垃圾值
private:
    int m_hour;              //声明
    int m_minute;
    int m_second;
};

class A          //A没写构造函数，会默认自动生成，但是Time有自己的构造函数，编译器不会自动生成，则导致找不到A的默认构造函数的报错
{
private:
    //基本内置类型
    int m_year = 1;         //声明缺省值,如果没写构造函数，默认初始值使用它
    int m_month = 1;
    int m_day = 1;
    //自定义类型
    Time _t;               //Time没有默认构造函数，会导致A也不能自动生成默认构造函数，报错
};

int main()
{
    A a1;
    return 0;
}
*/


/*
#include<iostream>
using namespace std;

class A {
public:
    A(int year=1)                                         //构造函数
    {
        m_year = year;
    }

    ~A()                                                //析构函数
    {
        cout << "调用析构函数~A()->" <<m_year<< endl;
    }

private:
    int m_year;
    int m_month;
    int m_day;
};

static A a11(11);

A a12(12);

static A a13(13);

void fun() {
    A a5(5);
    static A a6(6);
    A a7(7);
    static A a8(8);
}

A a14(14);
static A a15(15);

int main()
{
    //调用析构函数的顺序：局部对象（后定义先析构） -》 局部的静态 -》全局对象（后定义先析构）
    A a1;   
    A a2(2);
    A a3(3);
    static A a4(4);
    fun();
    static A a9(9);
    A a10(10);
}

*/
//一个类只有一个析构函数，未显示定义，编译器会默认自动生成一个默认的析构函数，析构函数不能重载，而构造函数可以
//对象声明周期结束时，C++编译器会自动调用析构函数